﻿#region Copyright & licence

// This file is part of Refix.
// 
// Refix is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
// 
// Refix is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public
// License along with Refix.  If not, see <http://www.gnu.org/licenses/>.
// 
// Copyright (C) 2010-11 David Musgrove and others.

#endregion

using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;

namespace Refix.Core.IO
{
    public class SolutionFile
    {
        private readonly Dictionary<Guid, ProjectFile> _cachedProjectFiles = new Dictionary<Guid, ProjectFile>();
        private readonly string _fileName;
        private readonly Regex _projectMatcher = new Regex(@"^Project\(.*\s=\s"".*?"",\s""(?<path>.*\.((cs)|(vb))proj?)""");
        private readonly Regex _solutionFolderMatcher = new Regex(@"^Project\(""\{2150E333-8FDC-42A3-9474-1A3956D46DE8\}"".*\s=\s"".*?"",\s""(?<path>.*)"",.*");
        private readonly Regex _environmentVariableMatcher = new Regex(@"((?<envvar>%.*%).*)*");
        private readonly List<ProjectFile> _projectFiles = new List<ProjectFile>();
        private readonly List<string> _solutionFolders = new List<string>();
        private readonly List<string> _fileLines = new List<string>();

        public SolutionFile(string fileName)
        {
            _fileName = fileName;
            using (StreamReader streamReader = File.OpenText(fileName))
            {
                while (!streamReader.EndOfStream)
                {
                    string line = streamReader.ReadLine();
                    _fileLines.Add(line);
                    Match match = _projectMatcher.Match(line);
                    if (match.Success)
                    {
                        string path = match.Groups["path"].Value;
                        path = ReplaceEnvironmentVariables(path);
                        path = Path.Combine(Path.GetDirectoryName(fileName), path);
                        if (File.Exists(path))
                        {
                            _projectFiles.Add(new ProjectFile(this, path));
                        }
                    }
                    match = _solutionFolderMatcher.Match(line);
                    if (match.Success)
                    {
                        string path = match.Groups["path"].Value;
                        path = ReplaceEnvironmentVariables(path);
                        _solutionFolders.Add(path);                        
                    }
                }
            }
        }

        public decimal GetTargetFrameworkVersion()
        {
            decimal targetVersion = decimal.MaxValue;
            foreach (var projectFile in _projectFiles)
            {
                decimal projectTarget = projectFile.GetTargetFrameworkVersion();
                if (projectTarget < targetVersion)
                {
                    targetVersion = projectTarget;
                }
            }
            if (targetVersion == decimal.MaxValue)
            {
                targetVersion = 2.0m;
            }
            return targetVersion;
        }

        private string ReplaceEnvironmentVariables(string path)
        {
            Match match = _environmentVariableMatcher.Match(path);
            if (match.Success)
            {
                foreach (Capture envvar in match.Groups["envvar"].Captures)
                {
                    path = path.Replace(envvar.Value, Environment.GetEnvironmentVariable(envvar.Value.Replace("%", "")));
                }
            }
            return path;
        }

        public string FileName
        {
            get { return _fileName; }
        }

        public List<string> SolutionFolders
        {
            get { return _solutionFolders; }
        }

        public Dictionary<Guid, ProjectFile> CachedProjectFiles
        {
            get { return _cachedProjectFiles; }
        }

        public List<string> FileLines
        {
            get { return _fileLines; }
        }
    }
}